@page "/visitor/visitors"


@using CleanArchitecture.Blazor.Application.Features.Visitors.Commands.Create
@using CleanArchitecture.Blazor.Application.Features.Visitors.Commands.Delete
@using CleanArchitecture.Blazor.Application.Features.Visitors.DTOs
@using CleanArchitecture.Blazor.Application.Features.Visitors.Queries.Pagination
@using CleanArchitecture.Blazor.Application.Features.Visitors.Commands.AddEdit
@using HashidsNet
@using System.Globalization

@inject IJSRuntime JS
@inject IStringLocalizer<Visitors> L
@attribute [Authorize(Policy = Permissions.Visitors.View)]
<PageTitle>@Title</PageTitle>
<style>
    .mud-table-toolbar {
        height: 84px !important;
    }
</style>
<ErrorBoundary>
    <ChildContent>
        <AdvancedSearchVisitorsComponent TRequest="query" OnFilterChanged="OnFilterChanged"></AdvancedSearchVisitorsComponent>
        <MudTable ServerData="@(new Func<TableState, Task<TableData<VisitorDto>>>(ServerReload))"
                  FixedHeader="true"
                  FixedFooter="true"
                  Virtualize="true"
                  Height="calc(100vh - 265px)"
                  Loading="@_loading"
                  SortLabel="@L["Sort By"]"
                  MultiSelection="true" @bind-SelectedItems="_selectedItems"
                  Hover="true" @ref="_table">
            <ToolBarContent>
                <div class="justify-start pt-3">
                    <MudText Typo="Typo.h6">@L["Visitors"]</MudText>
                    <MudHidden Breakpoint="Breakpoint.SmAndDown">
                        <MudButton DisableElevation Variant="Variant.Outlined"
                                   Size="Size.Small"
                                   Disabled="@_loading"
                                   OnClick="@(()=>OnRefresh())"
                                   StartIcon="@Icons.Material.Filled.Refresh" IconColor="Color.Surface" Color="Color.Primary"
                                   Style="margin-right: 4px; margin-bottom:4px">@L["Refresh"]</MudButton>
                        @if (_canApprove)
                        {
                            <MudButton DisableElevation Variant="Variant.Outlined" Color="Color.Primary"
                                   StartIcon="@Icons.Material.Filled.Approval"
                                   Disabled="@(!(_selectedItems.Count>0))"
                                   Size="Size.Small"
                                   OnClick="OnApproval"
                                   Style="margin-right: 4px; margin-bottom:4px"
                                   IconColor="Color.Surface">@L["Approve"]</MudButton>
                        }
                        @if (_canCreate)
                        {
                            <MudButton DisableElevation Variant="Variant.Outlined" Color="Color.Primary"
                                   StartIcon="@Icons.Material.Filled.Add"
                                   Disabled="@_loading"
                                   Size="Size.Small"
                                   OnClick="OnCreate"
                                   Style="margin-right: 4px; margin-bottom:4px"
                                   IconColor="Color.Surface">@L["Create"]</MudButton>
                        }
                        @if (_canDelete)
                        {
                            <MudButton DisableElevation Variant="Variant.Outlined" Color="Color.Error"
                                   StartIcon="@Icons.Material.Filled.Delete"
                                   Disabled="@(!(_selectedItems.Count>0))"
                                   Size="Size.Small"
                                   Style="margin-right: 4px; margin-bottom:4px"
                                   OnClick="OnDeleteChecked"
                                   IconColor="Color.Surface">@L["Delete"]</MudButton>
                        }
                        @if (_canImport)
                        {
                            <MudButton Disabled="@_uploading" DisableElevation Variant="Variant.Outlined" Color="Color.Primary"
                                   StartIcon="@Icons.Material.Filled.Upload"
                                   Size="Size.Small"
                                   Style="margin-right:1px; margin-bottom:4px"
                                   for="importdataInput"
                                   HtmlTag="label"
                                   IconColor="Color.Surface">
                                @if (_uploading)
                                {
                                    <MudProgressCircular Class="ms-n1" Size="Size.Small" Indeterminate="true" />
                                    <MudText Class="ms-2"> @L["Uploading..."]</MudText>
                                }
                                else
                                {
                                    <MudText>@L["Import Data"]</MudText>
                                }

                            </MudButton>
                            <InputFile id="importdataInput" OnChange="OnImportData" hidden accept=".xlsx" />
                        }
                        @if (_canExport)
                        {
                            <MudButton Disabled="@_downloading" DisableElevation Variant="Variant.Outlined" Color="Color.Primary"
                                   StartIcon="@Icons.Material.Filled.Download"
                                   Size="Size.Small"
                                   Style="margin-right: 4px; margin-bottom:4px"
                                   OnClick="OnExport"
                                   IconColor="Color.Surface">
                                @if (_downloading)
                                {
                                    <MudProgressCircular Class="ms-n1" Size="Size.Small" Indeterminate="true" />
                                    <MudText Class="ms-2"> @L["Downloading..."]</MudText>
                                }
                                else
                                {
                                    <MudText>@L["Export Data"]</MudText>
                                }
                            </MudButton>
                        }
                    </MudHidden>
                    <MudHidden Breakpoint="Breakpoint.SmAndDown" Invert="true">
                        <MudMenu AnchorOrigin="Origin.BottomLeft" StartIcon="@Icons.Filled.KeyboardCommandKey" EndIcon="@Icons.Filled.KeyboardArrowDown" Label="@L["Action"]" Color="Color.Primary" Variant="Variant.Filled">
                            <MudMenuItem Disabled="@_loading" OnClick="@(()=>OnRefresh())">@L["Refresh"]</MudMenuItem>
                            @if (_canApprove)
                            {
                                <MudMenuItem Disabled="@(!(_selectedItems.Count>0))" OnClick="OnApproval">@L["Approve"]</MudMenuItem>
                            }
                            @if (_canCreate)
                            {
                                <MudMenuItem Disabled="@_loading" OnClick="OnCreate">@L["Create"]</MudMenuItem>
                            }
                            @if (_canDelete)
                            {
                                <MudMenuItem OnClick="OnDeleteChecked">@L["Delete"]</MudMenuItem>
                            }
                            @if (_canImport)
                            {
                                <InputFile id="importdataInput" OnChange="OnImportData" hidden accept=".xlsx" />
                                <MudMenuItem for="importdataInput"
                                         HtmlTag="label">@L["Import Data"]</MudMenuItem>
                            }
                            @if (_canExport)
                            {
                                <MudMenuItem OnClick="OnExport">@L["Export Data"]</MudMenuItem>
                            }
                        </MudMenu>
                    </MudHidden>
                </div>
                <MudSpacer />
                <MudTextField T="string" ValueChanged="@(s=>OnSearch(s))" Value="@_searchString" Placeholder="Search" Adornment="Adornment.Start"
                              AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField>
            </ToolBarContent>
            <ColGroup>
                <col style="width:50px;" />
                <col style="width:120px;" />
            </ColGroup>
            <HeaderContent>
                <MudTh Style="width:80px">@L["Actions"]</MudTh>
                <MudTh><MudTableSortLabel SortLabel="Avatar" T="VisitorDto">@L["Visitor's Avatar"]</MudTableSortLabel></MudTh>
                <MudTh><MudTableSortLabel SortLabel="PassCode" T="VisitorDto">@L["Pass Code"]</MudTableSortLabel></MudTh>
                <MudTh><MudTableSortLabel SortLabel="Name" T="VisitorDto">@L["Visitor's Name"]</MudTableSortLabel></MudTh>
                <MudTh><MudTableSortLabel SortLabel="PhoneNumber" T="VisitorDto">@L["Phone Number"]</MudTableSortLabel></MudTh>
                <MudTh><MudTableSortLabel SortLabel="IdentificationNo" T="VisitorDto">@L["Identification No."]</MudTableSortLabel></MudTh>
                <MudTh><MudTableSortLabel SortLabel="Purpose" T="VisitorDto">@L["Purpose"]</MudTableSortLabel></MudTh>
                <MudTh><MudTableSortLabel SortLabel="Employee" T="VisitorDto">@L["Employee"]</MudTableSortLabel></MudTh>
                <MudTh><MudTableSortLabel SortLabel="ExpectedDate" T="VisitorDto">@L["Expected Date"]</MudTableSortLabel></MudTh>
                <MudTh><MudTableSortLabel SortLabel="CheckinDate" T="VisitorDto">@L["Check-in/out Time"]</MudTableSortLabel></MudTh>
                <MudTh><MudTableSortLabel SortLabel="TripCode" T="VisitorDto">@L["Trip Code"]</MudTableSortLabel></MudTh>
                <MudTh><MudTableSortLabel SortLabel="Apppoved" T="VisitorDto">@L["Apppoved"]</MudTableSortLabel></MudTh>
            </HeaderContent>
            <RowTemplate>
                <MudTd DataLabel="@L["Actions"]">
                    @if (_canEdit || _canDelete)
                    {
                        <MudMenu Label="@L["Actions"]" Variant="Variant.Filled" DisableElevation="true" Size="Size.Small"
                             Dense="true"
                             EndIcon="@Icons.Filled.KeyboardArrowDown" IconColor="Color.Info" Direction="Direction.Left"
                             OffsetX="true">
                            @if (_canEdit)
                            {
                                <MudMenuItem OnClick="@(()=>OnEdit(context))">@L["Edit"]</MudMenuItem>
                            }
                            @if (_canDelete)
                            {
                                <MudMenuItem OnClick="@(()=>OnDelete(context))">@L["Delete"]</MudMenuItem>
                            }
                        </MudMenu>
                    }
                    else
                    {
                        <MudButton Variant="Variant.Filled" DisableElevation="true"
                               StartIcon="@Icons.Material.Filled.DoNotTouch" IconColor="Color.Secondary" Size="Size.Small"
                               Color="Color.Surface">
                            @L["No Allowed"]
                        </MudButton>
                    }
                </MudTd>
                <MudTd HideSmall="true" DataLabel="@L["Visitor's Avatar"]">
                    @if (string.IsNullOrEmpty(context.Avatar))
                    {
                        <MudAvatar Image="@context.QrCode" Style="height:48px; width:48px; font-size:2rem; border-radius: --mud-default-borderradius !important" />
                    }
                    else
                    {
                        <MudAvatar Image="@context.Avatar" Style="height:48px; width:48px; font-size:2rem;" />
                    }
                </MudTd>
                <MudTd HideSmall="true" DataLabel="@L["Pass Code"]">@context.PassCode</MudTd>
                <MudTd DataLabel="@L["Visitor's Name"]">
                    <MudText>@context.Name</MudText>
                    <MudText Typo="Typo.body2">@context.CompanyName</MudText>
                </MudTd>
                <MudTd DataLabel="@L["Visitor's Phone Number"]">
                    <MudText>@context.PhoneNumber</MudText>
                    <MudText Typo="Typo.body2">@context.Email</MudText>
                </MudTd>

                <MudTd DataLabel="@L["Identification No."]">
                    <MudText>@context.IdentificationNo</MudText>
                </MudTd>
                <MudTd DataLabel="@L["Purpose"]">@context.Purpose</MudTd>
                <MudTd DataLabel="@L["Employee"]">
                    <MudText>@context.Employee</MudText>
                    <MudText Typo="Typo.body2">@context.EmployeeDesignation</MudText>
                </MudTd>
                <MudTd DataLabel="@L["Expected Date"]">
                    <MudText>@context.ExpectedDate?.ToString("MM/dd/yy",CultureInfo.InvariantCulture)</MudText>
                    @if (context.ExpectedTime is not null)
                    {
                        <MudText Typo="Typo.body2">@(new DateTime().Add(context.ExpectedTime.Value).ToString("hh:mm tt",CultureInfo.InvariantCulture))</MudText>
                    }
                </MudTd>
                <MudTd DataLabel="@L["Check-in/out Time"]">
                    <MudText Typo="Typo.body2">@context.CheckinDate</MudText>
                    <MudText Typo="Typo.body2">@context.CheckoutDate</MudText>
                </MudTd>
                <MudTd DataLabel="@L["Trip Code"]">
                    @if (context.TripCode is not null)
                    {
                        <MudTooltip Text="@L["Trip Code"]">
                            <MudIconButton OnClick="@(()=>OnShowPreview(context))" Icon="@Icons.Material.Filled.Route" aria-label="@L["Trip Code"]" Title="@L["Trip Code"]" />
                        </MudTooltip>
                    }
                    @if (context.HealthCode is not null)
                    {
                        <MudTooltip Text="@L["Health Code"]">
                            <MudIconButton OnClick="@(()=>OnShowPreview(context))" Icon="@Icons.Material.Filled.MonitorHeart" aria-label="@L["Health Code"]" Title="@L["Health Code"]" />
                        </MudTooltip>
                    }
                    @if (context.NucleicAcidTestReport is not null)
                    {
                        <MudTooltip Text="@L["Nucleic Acid Test Report"]">
                            <MudIconButton OnClick="@(()=>OnShowPreview(context))" Icon="@Icons.Material.Filled.FactCheck" aria-label="@L["Nucleic Acid Test Report"]" Title="@L["Nucleic Acid Test Report"]" />
                        </MudTooltip>
                    }
                </MudTd>
                <MudTd DataLabel="@L["Apppoved"]">
                    <MudCheckBox Disabled="true" Checked="@context.Apppoved"></MudCheckBox>
                    <MudText Typo="Typo.body2">@context.ApprovalOutcome</MudText>
                </MudTd>
            </RowTemplate>
            <NoRecordsContent>
                <MudText>@L["No matching records found"]</MudText>
            </NoRecordsContent>
            <LoadingContent>
                <MudText>@L["Loading..."].</MudText>
            </LoadingContent>
            <PagerContent>
                <MudTablePager />
            </PagerContent>
        </MudTable>
    </ChildContent>
    <ErrorContent>
        <CustomError Exception="context"></CustomError>
    </ErrorContent>
</ErrorBoundary>
@code {
    public string? Title { get; private set; }
    private HashSet<VisitorDto> _selectedItems = new HashSet<VisitorDto>();
    private MudTable<VisitorDto> _table = default!;
    private int _totalItems;
    private string _searchString = string.Empty;
    private bool _loading;
    private bool _uploading;
    private bool _downloading;
    [Inject]
    private ISender _mediator { get; set; } = default!;
    [Inject]
    private Hashids hashids { get; set; } = default!;
    [CascadingParameter]
    protected Task<AuthenticationState> AuthState { get; set; } = default!;

    private VisitorsWithPaginationQuery query { get; set; } = new();

    private bool _canSearch;
    private bool _canCreate;
    private bool _canEdit;
    private bool _canDelete;
    private bool _canApprove;
    private bool _canImport;
    private bool _canExport;
    protected override async Task OnInitializedAsync()
    {
        Title = L["Visitors"];
        var state = await AuthState;
        _canCreate = (await AuthService.AuthorizeAsync(state.User, Permissions.Visitors.Create)).Succeeded;
        _canSearch = (await AuthService.AuthorizeAsync(state.User, Permissions.Visitors.Search)).Succeeded;
        _canEdit = (await AuthService.AuthorizeAsync(state.User, Permissions.Visitors.Edit)).Succeeded;
        _canDelete = (await AuthService.AuthorizeAsync(state.User, Permissions.Visitors.Delete)).Succeeded;
        _canApprove = (await AuthService.AuthorizeAsync(state.User, Permissions.Visitors.Approve)).Succeeded;
        _canImport = false;
        _canExport = false;

    }
    private async Task<TableData<VisitorDto>> ServerReload(TableState state)
    {
        try
        {
            _loading = true;
            query.Keyword = _searchString;
            query.OrderBy = string.IsNullOrEmpty(state.SortLabel) ? "Id" : state.SortLabel;
            query.SortDirection = (state.SortDirection == SortDirection.None ? SortDirection.Descending.ToString() : state.SortDirection.ToString());
            query.PageNumber = state.Page + 1;
            query.PageSize = state.PageSize;
            var result = await _mediator.Send(query);
            return new TableData<VisitorDto>() { TotalItems = result.TotalItems, Items = result.Items };
        }
        finally
        {
            _loading = false;
        }

    }

    private void OnFilterChanged(string s)
    {
        InvokeAsync(async () =>
        {
            await _table.ReloadServerData();
        });
    }
    private async Task OnSearch(string text)
    {
        _selectedItems = new();
        _searchString = text;
        await _table.ReloadServerData();
    }
    private async Task OnRefresh()
    {
        _selectedItems = new();
        _searchString = string.Empty;
        await _table.ReloadServerData();
    }
    private async Task OnShowPreview(VisitorDto dto)
    {
        var parameters = new DialogParameters {
                 { nameof(_PreviewDialog.dto),dto }
            };
        var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small, FullWidth = true };
        var dialog = DialogService.Show<_PreviewDialog>
        (L["Preview upload pictures"], parameters, options);
        var state = await dialog.Result;
        if (!state.Cancelled)
        {
        }
    }
    private async Task OnApproval()
    {
        var parameters = new DialogParameters
            {

        { nameof(_ApprovalDialog.Selected),_selectedItems.ToList() },
            };
        var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small, FullWidth = true };
        var dialog = DialogService.Show<_ApprovalDialog>
        (L["Approval visitor request"], parameters, options);
        var state = await dialog.Result;
        if (!state.Cancelled)
        {
            var result = await _mediator.Send(new ApprovalVisitorsCommand(state.Data.ToString(), _selectedItems.Select(x => x.Id).ToArray()));
            await _table.ReloadServerData();
            Snackbar.Add($"{L["Approved successfully"]}", MudBlazor.Severity.Info);
        }
    }
    private async Task OnCreate()
    {
        var command = new AddEditVisitorCommand()
            {
                PassCode = hashids.EncodeLong(DateTime.Now.Ticks),
                Apppoved = false,
                PrivacyPolicy = true,
                Promise = true
            };
        var parameters = new DialogParameters
            {

        { nameof(_VisitorFormDialog.model),command },
            };
        var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Medium, FullWidth = true };
        var dialog = DialogService.Show<_VisitorFormDialog>
        (L["Create a new visitor"], parameters, options);
        var state = await dialog.Result;
        if (!state.Cancelled)
        {
            var result = await _mediator.Send(command);
            await _table.ReloadServerData();
            Snackbar.Add($"{L["Create successfully"]}", MudBlazor.Severity.Info);
        }
    }
    private async Task OnEdit(VisitorDto dto)
    {
        var command = new AddEditVisitorCommand()
            {
                Id = dto.Id,
                Name = dto.Name,
                PassCode = dto.PassCode,
                QrCode = dto.QrCode,
                Email = dto.Email,
                PhoneNumber = dto.PhoneNumber,
                IdentificationNo = dto.IdentificationNo,
                LicensePlateNumber = dto.LicensePlateNumber,
                Address = dto.Address,
                Gender = dto.Gender,
                CompanyName = dto.CompanyName,
                Purpose = dto.Purpose,
                Comment = dto.Comment,
                DesignationId = dto.DesignationId,
                EmployeeId = dto.EmployeeId,
                CheckinDate = dto.CheckinDate,
                CheckoutDate = dto.CheckoutDate,
                ExpectedDate = dto.ExpectedDate,
                ExpectedTime = dto.ExpectedTime,
                Avatar = dto.Avatar,
                TripCode = dto.TripCode,
                HealthCode = dto.HealthCode,
                NucleicAcidTestReport = dto.NucleicAcidTestReport,
                Status = dto.Status,
                Apppoved = dto.Apppoved,
                ApprovalOutcome = dto.ApprovalOutcome,
                PrivacyPolicy = dto.PrivacyPolicy,
                Promise = dto.Promise

            };
        var parameters = new DialogParameters
                {
            { nameof(_VisitorFormDialog.model),command },
                };
        var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Medium, FullWidth = true };
        var dialog = DialogService.Show<_VisitorFormDialog>
        (L["Edit the visitor"], parameters, options);
        var state = await dialog.Result;
        if (!state.Cancelled)
        {
            var result = await _mediator.Send(command);
            await _table.ReloadServerData();
            Snackbar.Add($"{L["Save successfully"]}", MudBlazor.Severity.Info);
        }
    }

    private async Task OnDelete(VisitorDto dto)
    {
        var deleteContent = L["You're sure you want to delete the Visitor:{0}?"];
        var parameters = new DialogParameters
                    {
                { nameof(DeleteConfirmation.ContentText), string.Format(deleteContent, dto.Name) }
                    };
        var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small, FullWidth = true, DisableBackdropClick = true };
        var dialog = DialogService.Show<DeleteConfirmation>
        (L["Delete"], parameters, options);
        var state = await dialog.Result;
        if (!state.Cancelled)
        {
            var command = new DeleteVisitorCommand(new int[] { dto.Id });
            var result = await _mediator.Send(command);
            await _table.ReloadServerData();
            Snackbar.Add($"{L["Deleted successfully"]}", MudBlazor.Severity.Info);
        }
    }

    private async Task OnDeleteChecked()
    {
        var deleteContent = L["You're sure you want to delete the selected items:{0}?"];
        var parameters = new DialogParameters
                        {
                    { nameof(DeleteConfirmation.ContentText), string.Format(deleteContent,_selectedItems.Count) }
                        };
        var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall, FullWidth = true, DisableBackdropClick = true };
        var dialog = DialogService.Show<DeleteConfirmation>
        (L["Delete"], parameters, options);
        var state = await dialog.Result;
        if (!state.Cancelled)
        {
            var command = new DeleteVisitorCommand(_selectedItems.Select(x => x.Id).ToArray());
            var result = await _mediator.Send(command);
            await _table.ReloadServerData();
            Snackbar.Add($"{L["Deleted successfully"]}", MudBlazor.Severity.Info);
            _selectedItems = new HashSet<VisitorDto>
            ();
        }
    }
    private void OnExport()
    {

    }
    private void OnImportData(InputFileChangeEventArgs e)
    {

    }
    }
